\ Lesson 3.     Numbers

 

comment:

 

In this lesson we shall discuss the way Forth handles integers.

Integers are numbers from -32768 to 32767.  This range of number

is most convenient to be stored and proceesed in Forth.  It is

very surprising that many real world problems can be represented

and solved using numbers in this range.  Forth can handle larger

numbers and even floating point numbers, but these are topics

outisde of the scope of this lesson.

 

 

Example 1.  Money Exchange

 

The first example we will use to demonstrate how numbers are

used in Forth is a money exchange program, which converts money

represented in different currencies.  Let's start with the

following currency exchange table:

 

        24.55 NT        1 Dollar

        7.73 HK         1 Dollar

        5.47 RMB        1 Dollar

        1 Ounce Gold    356 Dollars

        1 Ounce Silver  4.01 Dollars

 

We shall use the US dollar as the standard currency and convert

all other currencies to dollar first.  All arithmatic operations

then will be carried out in dollars.  From dollars, the money can

then be converted back to any other currency.

 

We define words converting other currencies to the dollar using

the names of the corresponding currencies.  To convert dollars

to a currency, the words is preceeded by the '$' sign.

 

comment;

 

: NT    ( nNT -- $ )    10 245 */  ;

: $NT   ( $ -- nNT )    245 10 */  ;

: RMB   ( nRMB -- $ )   100 547 */  ;

: $jmp  ( $ -- nJmp )   547 100 */  ;

: HK    ( nHK -- $ )    100 773 */  ;

: $HK   ( $ -- $ )      773 100 */  ;

: gold  ( nOunce -- $ ) 356 *  ;

: $gold ( $ -- nOunce ) 356 /  ;

: silver ( nOunce -- $ ) 401 100 */  ;

: $silver ( $ -- nOunce ) 100 401 */  ;

: ounce ( n -- n, a word to improve syntax )  ;

: dollars ( n -- )      . ;

 

comment:

 

With this set of money exchange words, we can do some tests:

 

        5 ounce gold .

        10 ounce silver .

        100 $NT .

        20 $RMB .

 

If you have many different currency bills in your wallet, you

can add then all up in dollars:

 

        1000 NT 500 HK + .s

        320 RMB + .s

        dollars ( print out total worth in dollars )

 

'DOLLARS' is idenitcal to '.', which simply displays a number.

Use 'DOLLARS' to display the total amount of money is natural

in the syntax of English.

 

If I am in Hong Kong at the time, the total amount can be

readily converted to Hong Kong dollars:

 

        1000 NT 500 HK + 320 RMB + .s

        $HK dollars ( convert total to Hong Kong dollar and print it)

 

 

Exercise 1.  A Business Trip

 

Now we have a fairly powerful money exchange computer with us.

Suppose you depart San Francisco with 1000 dollars in your pocket.

You go to Hong Kong and buy a VCR with 1200 HK. Go to Shanghai and

sell it for 2000 RMB.  Then you come back to Hong Kong and spent

900 HK for fun.  Go to Taipei and buy a portable PC with 30000 NT.

How much money in US dollar do you have remaining?

 

The answer typed backwards is:

 

        srallod - TN 00003 - KH 009 + BMR 0002 - KH 0021 0001

 

Try it.

 

 

Example 2. Temperature Conversion

 

Converting temperature readings between Celcius and Farenheit

is also an interesting problem.  The difference between temperature

conversion and money exchange is that the two temperature scales

have an offset besides the scaling factor.

 

comment;

 

: F>C ( nFarenheit -- nCelcius )

        32 -

        10 18 */

        ;

 

: C>F ( nCelcius -- nFarenheit )

        18 10 */

        32 +

        ;

 

comment:

 

90 F>C .        shows the temperature in a hot summer day and

0 C>F .         shows the temperature in a cold winter night.

 

In the above examples, we use the following Forth arithmatic

operators:

 

+       ( n1 n2 -- n1+n2 )      Add n1 and n2 and leave sum on stack.

-       ( n1 n2 -- n1-n2 )      Subtract n2 from n1 and leave differrence

                                on stack.

*       ( n1 n2 -- n1*n2 )      Multiply n1 and n2 and leave product

                                on stack.

/       ( n1 n2 -- n1/n2 )      Divide n1 by n2 and leave quotient on

                                stack.

*/      ( n1 n2 n3 -- n1*n2/n3) Multiply n1 and n2, divide the product

                                by n3 and leave quotient on the stack.

.s      ( ... -- ... )          Show the topmost 4 numbers on stack.

 

Here we have to introduce the concept of a stack.  A stack is a memory

area in the computer where numbers are stored and retrieved

implicitly.  It is different from variables discussed in Lesson 1.

Variables are named locations in memory, which are accessed by

referring to the assigned names.  Stack is a First-In-Last-out (FIFO)

list.  When a number is given to Forth, it is pushed on the stack.

Any operator which uses numbers pops the required numbers from the

stack.  The most accessible number is on the top of the stack, like

the card on the top of a card deck.  Various Forth instructions may

produce one or many numbers and the numbers are pushed on the stack

as they are generated.

 

+ thus pops the two topmost numbers off the stack, adds them together,

and then pushes the sum back on the stack.  -, *, and / are the

commonly used operators to do simple math.  One must notice that

the order of the two numbers used by + and * is immaterial, while the

order is important for - and /.  Exchanging the two numbers will produce

different difference or quotient, respectively.

 

*/ is a scaling operator in Forth, which is most useful in scaling

integer numbers.  It multiplies n1 by the ratio of (n2/n3).  As shown

in Examples 1 and 2, this operator is very useful in scaling

quantities from one unit to another.  Scaling is a very powerful

operation which eliminates the necessity of using floating point

numbers.

 

.s is a powerful debugging tool which shows you the contents of the

topmost 4 items on the stack.  It is used often during debugging

to make sure that the stack has the correct numbers for your

calculations.  It is generally not used in the final program to

avoid printing too many intermediate values.

 

Several other less commonly used, but important math operators are:

 

MOD     ( n1 n2 -- rem )        Divide n1 by n2 and leave the remainder

                                on stack.

/MOD    ( n1 n2 -- rem quot )   Divide n1 by n2 and leave both remainder

                                and quotient on stack.

ABS     ( n -- |n| )            Convert top number on stack to absolute.

NEGATE  ( n -- -n )             Negate n on stack.

 

As we go along, some of these operators will be used as occassions

arise.

 

 

Stack Operators

 

Stack is the most important place where the results of previously

executed operators can be passed to the operators yet to be executed.

Operators taking their parameters from the stack and leaving their

results on the stack for subsequent operator to use can be built

easily from stringing subroutines together.  The subroutines can call

other subroutines, and so forth.  The subroutines are Forth operators,

and they can be nested almost indefinitely.  This is a very important

reason why Forth is simple in its architecture and also in its

syntactical strucuture.

 

However, it happens very often that the odering of numbers on the

stack is not correct for a operator which needs them, like - and /.

There is a set of stack operators which rearranges numbers on the

stack.  The five most important classic stack operators are:

 

DUP     ( n -- n n )            Duplicate the top of stack.

SWAP    ( n1 n2 -- n2 n1 )      Exchange to top two numbers on stack.

OVER    ( n1 n2 -- n1 n2 n1 )   Duplicate the second number on stack.

ROT     ( n1 n2 n3 -- n2 n3 n1) Rotate 3rd number to the top of stack.

DROP    ( n -- )                Discard the top of stack.

 

 

Example 3.  Rectangles

 

A rectangle is specified by the (x,y) coordinates of its upper-left

and lower-right corners.  With these four integers on the stack,

we can compute the area, the center, and the perimenter of a

rectangle:

 

: area ( x1 y1 x2 y2 -- area )

        ROT -   ( x1 x2 y2-y1 )

        SWAP ROT - ( y2-y1 x2-x1 )

        * ( area )

        ;

 

: center ( x1 y1 x2 y2 -- x3 y3 , center coordinates )

        ROT - 2/ ( x1 x2 y3 )

        SWAP ROT - 2/ ( y3 x3 )

        SWAP ( x3 y3 )

        ;

 

: sides ( x1 y1 x2 y2 -- sides )

        ROT - ABS ( x1 x2 y2-y1 )

        SWAP ROT - ABS ( y2-y1 x2-x1 )

        + ( sides )

        ;

 

 

Logic Operators

 

Computer uses logic operators to determine and follow different execution

paths.  Logic operators themselves are very simple and easy to

understand.  However, the combination of many levels of logic

operations and the multitude of different pathways in a large

program make the computer seem very complicated, even to the point

of showing some intelligence.

 

Here we introduce some of the logic operators associated with

numbers, and the branching operators which use the results of

logic operators to select different operations.

 

Forth uses numbers to represent logic levels.  There are only two

logic levels, true and false.  True is represented by any number

which is not zero, and false is represented by zero.  Which a Forth

logic operator returns a true level, it usually returns a -1.  The

number representing logic levels is also called a flag.

 

>       ( n1 n2 -- f )          Return true if n1>n2.  Otherwise

                                return false.

<       ( n1 n2 -- f )          Return true if n1<n2.

=       ( n1 n2 -- f )          Return true if n1=n2.

0=      ( n -- f )              Return true if n=0.

0<      ( n -- f )              Return true if n<0.

NOT     ( f1 -- f2 )            Return true if f1 is false.  Return

                                false if f1 is true.

AND     ( n1 n2 -- n3 )         n3 is bitwise AND of n1 and n2.

OR      ( n1 n2 -- n3 )         N3 is bitwise OR of n1 and n2.

 

Note that AND and OR will operate correctly on true and false flags.

 

        true true AND   --      true

        true false AND  --      false

        false false AND --      false

        true true OR    --      true

        true false OR   --      true

        false false OR  --      flase

 

A flag can be used to select one of the two execution paths by

the following constructs inside a colon definition:

 

        ( f ) IF <true clause> ELSE <false clause> THEN

        ( f ) IF <true clause> THEN

 

They were briefly discussed in Lesson 2.  Now that we know how to

generate flags, you will appreciate them better in conjunction with

the logic instructions.

 

 

Example 4.  Weather Reporting.

 

The following colon definition illustrates the use of logic and

the branch:

 

comment;

 

: weather ( nFarenheit -- )

        DUP     85 >

        IF      ." Too hot!" DROP

        ELSE    55 <

                IF      ." Too cold."

                ELSE    ." About right."

                THEN

        THEN

        ;

 

comment:

 

You can type the following instructions and get some responses from the

computer:

 

        90 weather  Too hot!

        70 weatehr  About right.

        32 weather  Too cold.

 

 

Review of Loop instructions

 

We shall be concerned now with only the definite loop instructions

used in the following format in a colon definition:

 

        ( nLimit nIndex ) DO <repeat clause> LOOP

 

DO takes two parameters off the stack.  The top number is the

starting index of the loop and the second number is the upper

limit of the loop index.  After entering the loop,

the <repeat clause> is repeatedly executed.  LOOP increments the

loop index from nIndex to nLimit.  When the index is equal to

nLimit, the loop is terminated.  In the <repeat clause> a special

operator I returns the current loop index on the stack.

 

A simple example of the loop structure is as follows:

 

 

Example 5.  Print the multiplication table

 

comment;

 

: OneRow ( nRow -- )

        CR

        DUP 3 .R 3 SPACES

        13 1

        DO      I OVER *

                4 .R

        LOOP

        DROP ;

 

: Table ( -- )

        CR CR 6 SPACES

        13 1

        DO      I 4 .R  LOOP    ( display column numbers )

        13 1

        DO      I OneRow

        LOOP

        ;

 

comment:

 

Typing TABLE will cause the multiplication table to be displayed

in a very neat format.

 

 

Exercise 1.     In US, the multiplation table ends at 12*12.  In

China and most metric countries, the multiplication table usually

ends at 9*9.  Modify the definition of TABLE so that the table

is limited from 1*1 to 9*9.

 

With all these new Forth operator introduced, we can now write

a fairly substantial program using many of the operators to

demonstrate how they are combined to do some useful work.

 

comment;